<?

/* daemon options */
define('WAIT_BETWEEN_ENCODINGS', '1');

/* path & log options */
define('PATH_UPLOADED_FILES', '/data/temp');
define('PATH_STORAGE', '/data/files');
define('PATH_TEMP', '/tmp');
define('LOG_ERROR', false);
define('LOG_ACTIVITY', false);
define('LOG_FILE', '/tmp/idoovideo.log');
define('HTTP_STORAGE', 'http://up1.idoovideo.com/files');
define('HTTP_CALLBACK', 'http://lordgun.partners.idoo.com/idoovideo/post.php');

/* ffmpeg options */
define('FFMPEG_PATH', '/usr/bin/ffmpeg' );
define('BITRATE', '400000' );
$outputSizes = array( '640x480', '512x384', '480x360', '416x312', '400x300', '320x240' );
define('VIDEO_FPS', 20 );
define('AUDIO_BITRATE', 64000 );
define('AUDIO_R', 44100 );
define('AUDIO_FORCE_MONO', true );
define('MAX_LENGTH', 15);

/* idoo */
define('NB_THUMBNAILS', 4);




/* NOTHING TO MODIFY BELOW THIS LINE */

$extension = "ffmpeg";
$extension_soname = $extension . "." . PHP_SHLIB_SUFFIX;
$extension_fullname = PHP_EXTENSION_DIR . "/" . $extension_soname;

// load extension
if(!extension_loaded($extension)) {
	dl($extension_soname) or die("Can't load extension $extension_fullname\n");
}

error_reporting(E_ALL);
set_time_limit(0);

if ( (!is_file(FFMPEG_PATH)) || (!is_readable(FFMPEG_PATH)) || (!is_executable(FFMPEG_PATH)) )
	ilog('Cannot find/read/execute ffmpeg ('.FFMPEG_PATH.")\n");
if (!@chdir(PATH_UPLOADED_FILES))
	ilog('Cannot chdir to upload directory ('.PATH_UPLOADED_FILES.")\n");



$cmd_raw = FFMPEG_PATH.' -i __SOURCE__ -acodec libmp3lame -ac __AUDIO_CHANNELS__ -ab '.AUDIO_BITRATE.' -ar '.AUDIO_R.
			' -f flv -s __OUTPUT_SIZE__ -passlogfile '.PATH_TEMP.'/idoovideo.log __PASS__  -r '.VIDEO_FPS.
			' -b '.BITRATE.' -t 00:'.MAX_LENGTH.':00 -y  __TARGET__ ';

// -minrate '.(BITRATE/2).' -maxrate '.(BITRATE*2).' -bufsize 128000 -t 00:01:00

$descriptorspec = array(
	0 => array("pipe", "r"),
	1 => array("pipe", "w"),
	2 => array("pipe", "w")
);
$env = array();


while(TRUE) {

	$files = array();

	// we need to sort the current files
	foreach(glob(PATH_UPLOADED_FILES.'/*') as $file) {
	        $tmp = (object)null;
	        $tmp->fullname = $file;
			$tmp->name = basename($file);
	        $tmp->timestamp = filemtime($file);
	        $tmp->date = date('r', $tmp->timestamp);
	        $files[] = $tmp;
	}

	// no file ?
	if (!empty($files)) {

		$begin = time();

		usort($files, "dateCompare");

		$ok = false;

		// we take the oldest one
		if (isset($files[0])) {
			$file = $files[0];
			echo "\n".date('c')."  ".str_pad(substr($file->name,0,20) ,22);
			$ok = true;
		}
	

		$file_source = escapeshellarg($file->fullname);
		$file_target = escapeshellarg( PATH_TEMP.'/'.$file->name.'.flv' );


		// get info about the file using ffmpeg-php

		if ($ok) {
			$movie = @new ffmpeg_movie($file->fullname);
			if ( ($movie==false) || (!$movie->getFrameWidth()) ) {
				$ok = false;
				echo "KO";
			}
				else echo str_pad('['.$movie->getFrameWidth().'x'.$movie->getFrameHeight().':'.intval(@$movie->getDuration()).'"]', 20 );
		}


		if ($ok) {

			// define the output size as the biggest possible

			$max = explode('x', $outputSizes[0] );
			$targetWidth = $max[0];
			$targetHeight = $max[1];


			// we try to use the smallest size without loosing quality

			foreach ($outputSizes as $size) {
				$tsize = explode('x', $size );
				if ( (intval($tsize[0]) >= $movie->getFrameWidth()) && (intval($tsize[1]) >= $movie->getFrameHeight()) ) {
					$targetWidth = $tsize[0];
					$targetHeight = $tsize[1];
				}
			}
			unset($max, $size, $tsize);


			// correct paddings

			// Height and Width have to be multiples of 2
			$twidth = $movie->getFrameWidth();
			if ($twidth%2!=0) 
				$twidth--;
			$theight = $movie->getFrameHeight();
			if ($theight%2!=0)
				$theight--;

			$padTop = round( ( $targetHeight - $theight ) / 2 );
			$padBottom = $targetHeight - $theight - $padTop;
			$padLeft = round( ( $targetWidth - $twidth ) / 2 );
			$padRight = $targetWidth - $twidth - $padLeft;

			if ($padTop%2!=0) $padTop--;
			if ($padBottom%2!=0) $padBottom--;
			if ($padLeft%2!=0) $padLeft--;
			if ($padRight%2!=0) $padRight--;

			$width = $targetWidth-$padLeft-$padRight; 
			$height = $targetHeight-$padTop-$padBottom; 

			echo str_pad("[{$targetWidth}x{$targetHeight}:{$padTop}:{$padBottom}:{$padLeft}:{$padRight}]", 24 );

		}
/*
		// ratio

		$targetHeight = round( $maxWidth * $movie->getFrameHeight() / $movie->getFrameWidth() );
		if ($targetHeight < $maxHeight)
			$padTop = $padBottom = round( ($maxHeight - $targetHeight) /2 );

		$ratio = $movie->getFrameWidth() / $movie->getFrameHeight();

		$aspect = '-padtop '.$padTop.' -padbottom '.$padBottom;
		$maxHeight = $maxHeight - $padTop - $padBottom;
*/

/*
		// resize X
		if ($movie->getFrameWidth()>$maxWidth) {
			$targetHeight = round( $movie->getFrameHeight() * $maxWidth / $targetWidth );
			$targetWidth = $maxWidth;
		}

		// resize Y
		if ($movie->getFrameHeight()>$maxHeight) {
			$targetWidth = round( $movie->getFrameWidth() * $maxHeight / $targetHeight );
			$targetHeight = $maxHeight;
		}
*/


		// audio settings (if 0 channel is present, ffmpeg-php throws a warning so we need @ operator)

		if ( AUDIO_FORCE_MONO || (@$movie->getAudioChannels()!=2) )
			$channels = 1;
		else
			$channels = 2;


		// first pass

		if ($ok) {

			echo "Pass 1  ";

			$cmd = $cmd_raw;
			//$cmd = str_replace('__PASS__', '-pass 1', $cmd);
			$cmd = str_replace('__PASS__', '', $cmd);
			$cmd = str_replace('__SOURCE__', $file_source, $cmd);
			$cmd = str_replace('__TARGET__', $file_target, $cmd);
			$cmd = str_replace('__AUDIO_CHANNELS__', $channels, $cmd);
			$cmd = str_replace('__OUTPUT_SIZE__', "{$width}x{$height} -padtop {$padTop} -padbottom {$padBottom} -padleft {$padLeft} -padright {$padRight}", $cmd);

			$process = proc_open($cmd, $descriptorspec, $pipes, '.', $env);
			if (is_resource($process)) {
				fwrite($pipes[0], '');
				fclose($pipes[0]);
				$res = stream_get_contents($pipes[1]);
				fclose($pipes[1]);
				$res.= stream_get_contents($pipes[2]);
				fclose($pipes[2]);
				if (proc_close($process)!=0)
					$ok = false;
			} else 
				$ok = false;

			if (!$ok)
				logFile("\n\n$cmd\n\n$res\n\n");
			
		}
	
/*
		// second pass

		if ($ok) {

			echo "Pass 2  ";

			$cmd = str_replace('-pass 1', '-pass 2', $cmd);
	
			$process = proc_open($cmd, $descriptorspec, $pipes, '.', $env);
			if (is_resource($process)) {
				fwrite($pipes[0], '');
				fclose($pipes[0]);
				$res = stream_get_contents($pipes[1]);
				fclose($pipes[1]);
				$res.= stream_get_contents($pipes[2]);
				fclose($pipes[2]);
				if (proc_close($process)!=0)
					 $ok = false;
			} else
				$ok = false;

			if (!$ok)
				logFile("\n\n$cmd\n\n$res\n\n");
		}
*/

		// we check the correct folder
		// and create it if it does not exist
	
		$folder1 = substr(strtolower($file->name),0,1);
		$folder2 = substr(strtolower($file->name),1,1);
	
		if ( ($ok) && (!is_dir(PATH_STORAGE.'/'.$folder1)) )
			if (!mkdir(PATH_STORAGE.'/'.$folder1)) {
				ilog("Cannot create folder ".PATH_STORAGE.'/'.$folder1);
				$ok = false;
			}

		if ( ($ok) && (!is_dir(PATH_STORAGE.'/'.$folder1.'/'.$folder2)) )
			if (!mkdir(PATH_STORAGE.'/'.$folder1.'/'.$folder2)) {
				ilog("Cannot create folder ".PATH_STORAGE.'/'.$folder1.'/'.$folder2);
				$ok = false;
			}
	

		// we move the file
	
		if ($ok) {
			$target = PATH_STORAGE.'/'.vrealPath($file->name.'.flv');
			if (!rename( PATH_TEMP.'/'.$file->name.'.flv' , $target )) {
				$ok = false;
				ilog('Cannot move file '. PATH_TEMP.'/'.$file->name.'.flv' .' to '. PATH_STORAGE.'/'.vrealPath($file->name) );
			}
		}


		// we need to create NB_THUMBNAILS thumbnails

		if ($ok) {

			echo "Thumbs  ";
			$movie = new ffmpeg_movie($target);
			$step = round($movie->getFrameCount()/NB_THUMBNAILS);

			for ($a=0; $a<NB_THUMBNAILS; $a++) {
/*
				// get the frame
				$thumbs = $movie->getFrame(1+$step*$a);
				$thumbs2 = clone $thumbs;
*/
				// get the frame from our new video
				$thumbs = $movie->getFrame(1+$step*$a);
				$thumbs2 = clone $thumbs;

				// resizes
				$thumbs->resize( 110, 84 );
				$thumbs2->resize( 82, 62 );

				// we write the jpegs
				imagejpeg($thumbs->toGDImage(), PATH_STORAGE.'/'.vrealPath($file->name.'_110x84_'.$a.'.jpg') ,80);
				imagejpeg($thumbs2->toGDImage(), PATH_STORAGE.'/'.vrealPath($file->name.'_82x62_'.$a.'.jpg') ,80);

			}

			unset($thumbs);
			unset($thumbs2);
			
		}


		// successfull or not, we have to delete the file

		@unlink($file->fullname);


		// and we call idoo with the final result

		if ($ok)
			$status = 1;
		else
			$status = 0;

		$answer='<'.'?xml version="1.0" encoding="UTF-8"?>';
		$answer.= "\n<video_encoded>\n\t".
			'<video status="'.$status.'" country="FR" lang="fr"';
		if ($ok)
			$answer.=' duration="'.intval(@$movie->getDuration()).'" size="'.$targetWidth.'x'.$targetHeight.'"';
		$answer.=' id="'.$file->name.'">'. "\n";
		if ($ok) {
			$answer.= "\t<url_video><![CDATA[" .vrealPath($file->name.'.flv', true). "]]></url_video>\n";
			$answer.= "\t<images>\n";
			for ($a=0; $a<NB_THUMBNAILS; $a++)
				$answer.= "\t\t".'<image type="82x62"><![CDATA['.vrealPath($file->name.'_82x62_'.$a.'.jpg', true).']]></image>'."\n";
			for ($a=0; $a<NB_THUMBNAILS; $a++)
				$answer.= "\t\t".'<image type="110x84"><![CDATA['.vrealPath($file->name.'_110x84_'.$a.'.jpg', true).']]></image>'."\n";
			$answer.= "\t</images>\n";
		}
		$answer.= "</video>\n</video_encoded>";

		$_POST = (array)null;
		$_POST['xmlvideo'] = $answer;

		$rCurl = curl_init();
		curl_setopt ($rCurl, CURLOPT_URL, HTTP_CALLBACK );
		curl_setopt ($rCurl, CURLOPT_HEADER, false);
		curl_setopt ($rCurl, CURLOPT_POST, true);
		curl_setopt ($rCurl, CURLOPT_POSTFIELDS, $_POST);
		curl_setopt ($rCurl, CURLOPT_RETURNTRANSFER, true);

		if (!$cResult = curl_exec ($rCurl))
			$ok = false;

		curl_close ($rCurl);	
		echo "HAK  ";

		unset($thumbsUrl);
		unset($movie);

		// final result

		if ($ok) {
			echo "OK (";
			echo (time()-$begin).'s)';
		}
		else
			echo "KO";

	}

	sleep(WAIT_BETWEEN_ENCODINGS);

}

exit;




/* functions */

function dateCompare($a, $b) {
	if ($a->timestamp == $b->timestamp) return 0;
	return ($b->timestamp < $a->timestamp) ? -1 : 1;
}

function ilog($log) {
	die($log."\n");
}

function logFile($error) {
	$f = fopen(LOG_FILE, 'a+');
	fputs($f, $error);
	fclose($f);
}

// returns a hashed path, with or without entire url
// i.e. realPath('blublu.flv', true) == "http://storage.idoo.com/b/l/blublu.flv'

function vrealPath($file, $http=false) {
	$folder1 = substr(strtolower($file),0,1);
	$folder2 = substr(strtolower($file),1,1);
	$path = $folder1.'/'.$folder2.'/'.$file;
	if ($http)
		return HTTP_STORAGE.'/'.$path;
	else
		return $path;
}

function execCmd($commande) {
	$edescriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") );
	$eenv = array();

	$eprocess = proc_open($commande, $edescriptorspec, $epipes, '.', $eenv);
	if (is_resource($eprocess)) {
		fwrite($epipes[0], '');
		fclose($epipes[0]);
		$ok = stream_get_contents($epipes[1]);
		fclose($epipes[1]);
		$ok .= stream_get_contents($epipes[2]);
		fclose($epipes[2]);
		echo $ok;
		if (proc_close($eprocess)!=0)
			$ok = false;
	} else
		$ok = false;

	return $ok;
}

?>
